home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 4: GNU Archives / Linux Cubed Series 4 - GNU Archives.iso / gnu / glibc-1.09 / glibc-1 / glibc-1.09.1 / sysdeps / unix / bsd / sun / sparc / sigtramp.c < prev   
Encoding:
C/C++ Source or Header  |  1994-07-18  |  6.4 KB  |  247 lines

  1. /* Copyright (C) 1991, 1992, 1994 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3.  
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Library General Public License as
  6. published by the Free Software Foundation; either version 2 of the
  7. License, or (at your option) any later version.
  8.  
  9. The GNU C Library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12. Library General Public License for more details.
  13.  
  14. You should have received a copy of the GNU Library General Public
  15. License along with the GNU C Library; see the file COPYING.LIB.  If
  16. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  17. Cambridge, MA 02139, USA.  */
  18.  
  19. #include <ansidecl.h>
  20.  
  21. #ifndef    __GNUC__
  22.   #error This file uses GNU C extensions; you must compile with GCC.
  23. #endif
  24.  
  25. /* Get the definition of `struct sigcontext'.  */
  26. #define    KERNEL
  27. #define    sigvec        sun_sigvec
  28. #define    sigstack    sun_sigstack
  29. #define    sigcontext    sun_sigcontext
  30. #include "/usr/include/sys/signal.h"
  31. #undef    sigvec
  32. #undef    sigstack
  33. #undef    sigcontext
  34. #undef    NSIG
  35. #undef    SIGABRT
  36. #undef    SIGCLD
  37. #undef    SV_ONSTACK
  38. #undef    SV_RESETHAND
  39. #undef    SV_INTERRUPT
  40. #undef    SA_ONSTACK
  41. #undef    SA_NOCLDSTOP
  42. #undef    SIG_ERR
  43. #undef    SIG_DFL
  44. #undef    SIG_IGN
  45. #undef    sigmask
  46. #undef    SIG_BLOCK
  47. #undef    SIG_UNBLOCK
  48. #undef    SIG_SETMASK
  49.  
  50. #include <signal.h>
  51. #include <stddef.h>
  52. #include <errno.h>
  53.  
  54. /* Defined in __sigvec.S.  */
  55. extern int EXFUN(__raw_sigvec, (int sig, CONST struct sigvec *vec,
  56.                 struct sigvec *ovec));
  57.  
  58. /* User-specified signal handlers.  */
  59. #define mytramp 1
  60. #ifdef mytramp
  61. static __sighandler_t handlers[NSIG];
  62. #else
  63. #define handlers _sigfunc
  64. extern __sighandler_t _sigfunc[];
  65. #endif
  66.  
  67. #if mytramp
  68.  
  69. /* Handler for all signals that are handled by a user-specified function.
  70.    Saves and restores the general regs %g2-%g7, the %y register, and
  71.    all the FPU regs (including %fsr), around calling the user's handler.  */
  72. static void
  73. DEFUN(trampoline, (sig), int sig)
  74. {
  75.   /* We use `double' and `long long int' so `std' (store doubleword) insns,
  76.      which might be faster than single-word stores, will be generated.  */
  77.   register double f0 asm("%f0");
  78.   register double f2 asm("%f2");
  79.   register double f4 asm("%f4");
  80.   register double f6 asm("%f6");
  81.   register double f8 asm("%f8");
  82.   register double f10 asm("%f10");
  83.   register double f12 asm("%f12");
  84.   register double f14 asm("%f14");
  85.   register double f16 asm("%f16");
  86.   register double f18 asm("%f18");
  87.   register double f20 asm("%f20");
  88.   register double f22 asm("%f22");
  89.   register double f24 asm("%f24");
  90.   register double f26 asm("%f26");
  91.   register double f28 asm("%f28");
  92.   register double f30 asm("%f30");
  93.   register long long int g2 asm("%g2");
  94.   register long long int g4 asm("%g4");
  95.   register long long int g6 asm("%g6");
  96.   register int *fp asm("%fp");
  97.  
  98.   int code;
  99.   register struct sigcontext *context asm("%i0"); /* See end of fn.  */
  100.   PTR addr;
  101.   int y;
  102.   double fpsave[16];
  103.   int fsr;
  104.   int savefpu;
  105.   long long int glsave[3];
  106.  
  107.   /* SIG isn't really passed as an arg.
  108.      The args to the signal handler are at fp[16..19].  */
  109.   sig = fp[16];
  110.   code = fp[17];
  111.   context = (struct sigcontext *) fp[18];
  112.   addr = (PTR) fp[19];
  113.  
  114.   /* Save the Y register.  */
  115.   asm("rd %%y, %0" : "=r" (y));
  116.  
  117.   /* Save the FPU regs if the FPU enable bit is set in the PSR,
  118.      and the signal isn't an FP exception.  */
  119.   savefpu = (context->sc_psr & 0x1000) && sig != SIGFPE;
  120.   if (savefpu)
  121.     {
  122.       fpsave[0] = f0;
  123.       fpsave[1] = f2;
  124.       fpsave[2] = f4;
  125.       fpsave[3] = f6;
  126.       fpsave[4] = f8;
  127.       fpsave[5] = f10;
  128.       fpsave[6] = f12;
  129.       fpsave[7] = f14;
  130.       fpsave[8] = f16;
  131.       fpsave[9] = f18;
  132.       fpsave[10] = f20;
  133.       fpsave[11] = f22;
  134.       fpsave[12] = f24;
  135.       fpsave[13] = f26;
  136.       fpsave[14] = f28;
  137.       fpsave[15] = f30;
  138.  
  139.       /* Force it into a stack slot so the asm won't barf.  Sigh.  */
  140.       (void) &fsr;
  141.       asm("st %%fsr, %0" : "=m" (fsr));
  142.     }
  143.  
  144.   /* Save the global registers (except for %g1, which is a scratch reg).  */
  145.   glsave[0] = g2;
  146.   glsave[1] = g4;
  147.   glsave[2] = g6;
  148.  
  149.   /* Call the user's handler.  */
  150.   (*((void EXFUN((*), (int sig, int code, struct sigcontext *context,
  151.                PTR addr))) handlers[sig]))
  152.     (sig, code, context, addr);
  153.  
  154.   /* Restore the Y register.  */
  155.   asm("mov %0, %%y" : : "r" (y));
  156.  
  157.   if (savefpu)
  158.     {
  159.       /* Restore the FPU regs.  */
  160.       f0 = fpsave[0];
  161.       f2 = fpsave[1];
  162.       f4 = fpsave[2];
  163.       f6 = fpsave[3];
  164.       f8 = fpsave[4];
  165.       f10 = fpsave[5];
  166.       f12 = fpsave[6];
  167.       f14 = fpsave[7];
  168.       f16 = fpsave[8];
  169.       f18 = fpsave[9];
  170.       f20 = fpsave[10];
  171.       f22 = fpsave[11];
  172.       f24 = fpsave[12];
  173.       f26 = fpsave[13];
  174.       f28 = fpsave[14];
  175.       f30 = fpsave[15];
  176.  
  177.       asm("ld %0, %%fsr" : : "m" (fsr));
  178.     }
  179.  
  180.   /* Restore the globals.  */
  181.   g2 = glsave[0];
  182.   g4 = glsave[1];
  183.   g6 = glsave[2];
  184.  
  185.   /* Unwind a frame, and do a "sigcleanup" system call.
  186.      The system call apparently does a return.
  187.      I don't know what it's for.  Ask Sun.  */
  188.   asm("restore %%g0, 139, %%g1\n"
  189.       "ta 0\n"
  190.       "! this should be i0: %0"    /* Useless insn that will never be executed, */
  191.                 /* here to make the compiler happy.  */
  192.       : /* No outputs.  */ :
  193.       /* CONTEXT is bound to %i0.  We reference it as an input here to make
  194.      sure the compiler considers it live at this point, and preserves
  195.      the value in that register.  The restore makes %i0 become %o0, the
  196.      argument to the system call.  */
  197.       "r" (context));
  198. }
  199. #endif
  200.  
  201. int
  202. DEFUN(__sigvec, (sig, vec, ovec),
  203.       int sig AND CONST struct sigvec *vec AND struct sigvec *ovec)
  204. {
  205. #ifndef    mytramp
  206.   extern void _sigtramp (int);
  207. #define    trampoline    _sigtramp
  208. #endif
  209.   struct sigvec myvec;
  210.   int mask;
  211.   __sighandler_t ohandler;
  212.  
  213.   if (sig <= 0 || sig >= NSIG)
  214.     {
  215.       errno = EINVAL;
  216.       return -1;
  217.     }
  218.  
  219.   mask = __sigblock(sigmask(sig));
  220.  
  221.   ohandler = handlers[sig];
  222.  
  223.   if (vec != NULL &&
  224.       vec->sv_handler != SIG_IGN && vec->sv_handler != SIG_DFL)
  225.     {
  226.       handlers[sig] = vec->sv_handler;
  227.       myvec = *vec;
  228.       myvec.sv_handler = trampoline;
  229.       vec = &myvec;
  230.     }
  231.  
  232.   if (__raw_sigvec(sig, vec, ovec) < 0)
  233.     {
  234.       int save = errno;
  235.       (void) __sigsetmask(mask);
  236.       errno = save;
  237.       return -1;
  238.     }
  239.  
  240.   if (ovec != NULL && ovec->sv_handler == trampoline)
  241.     ovec->sv_handler = ohandler;
  242.  
  243.   (void) __sigsetmask(mask);
  244.  
  245.   return 0;
  246. }
  247.